package ch.fhnw.apsi.services;

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import ch.fhnw.apsi.Page;
import ch.fhnw.apsi.beans.Credentials;
import ch.fhnw.apsi.db.DB;
import ch.fhnw.apsi.db.DBManager;
import ch.fhnw.apsi.db.InvalidInputException;
import ch.fhnw.apsi.password.PasswordHash;

public class SetPW implements Service {
  @Override
  public ServiceResult process(final HttpServletRequest request, final HttpServletResponse response) {
    final HttpSession session = request.getSession();
    if ("POST".equals(request.getMethod())) {
      final String passwort0 = request.getParameter("passwort0");
      final String passwort1 = request.getParameter("passwort1");
      final String passwort2 = request.getParameter("passwort2");
      if (passwort0 == null || passwort0.isEmpty())
        return ServiceResult.error(400, "Es wurde kein bestehendes Passwort angegeben.");

      if (passwort1 == null || passwort1.isEmpty())
        return ServiceResult.error(400, "Es wurde kein neues Passwort angegeben.");
      if (!passwort1.equals(passwort2))
        return ServiceResult.error(400, "Es wurden zwei unterschiedliche Passwörter angegeben.");
      try {
        Credentials.validatePassword(passwort1);
      } catch (final InvalidInputException e) {
        return ServiceResult.error(400, e.getMessage());
      }

      // The user is logged in so the session must have Credentials.
      final Credentials oldCreds = (Credentials) session.getAttribute("login");
      try {
        if (!PasswordHash.validatePassword(passwort0, oldCreds.getPasswortHash()))
          return ServiceResult.error(500, "Das angegebene Passwort ist nicht korrekt.");
      } catch (NullPointerException | NoSuchAlgorithmException | InvalidKeySpecException e1) {
        return ServiceResult.error(500, "Fataler Fehler!");
      }

      // Let's create new Credentials:
      final Credentials newCreds = new Credentials(oldCreds.getUsername(), passwort1.toCharArray(), false,
          oldCreds.getFirmaId());

      try {
        final DB db = DBManager.getDB();
        if (!db.isValid())
          throw new SQLException();
        db.updateCredentials(newCreds);
      } catch (final SQLException e) {
        return ServiceResult.error(500, "Fataler Fehler!");
      }
      session.setAttribute("login", newCreds);
      return ServiceResult.success("Das Passwort wurde erfolgreich angepasst.");
    }
    return new ServiceResult(new Object(), Page.SETPW); // Nothing get's out here!
  }
}
